package xnj.lazydog.bluetoothmaster.BlueTooth;

import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothSocket;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanResult;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.UUID;

import xnj.lazydog.bluetoothmaster.R;



/*
   本类支持所有蓝牙通信中需要用到的功能，主要包括三个方面：
   1.周围蓝牙设备的扫描，得到一个设备列表
   2.蓝牙设备的配对与连接
   3.与蓝牙设备的通信

   1.蓝牙扫描
       蓝牙扫描时，2，0类的蓝牙和BLE类的蓝牙同时进行扫描，然后扫描得到的设备放进同一个列表中
       开始扫描时，设备列表清空
       扫描到设备时，设备放入列表
       2.0扫描过程结束后，会产生Action，此时将BLE的扫描过程手动终止

   2.蓝牙设备的配对和连接
       在连接时，首先判断该设备是否已经绑定了，如果没有绑定，则进入绑定程序，绑定成功后，会恢复连接之前
       绑定结束后，重新连接，在线程中连接并等待，直到连接成功，2.0和BLE的连接方法是不同的，需要判断进行不同的操作

   3.蓝牙通信
       2.0和BLE的通信实现方式不同，因此需要对设备类型进行判断，2.0是得到一个socket，ble则是得到GATT

    */
public class BlueToothMaster {

    private static final byte PACK_HEAD = (byte) 0xa5;
    private static final byte PACK_TAIL = (byte) 0x5a;
    private static final int MAX_PACK_SIZE = 8192;
    private static final int MAX_BUFFER_SIZE = 20480;

    public static final int MODE_CHAT = 0;    // 对话模式 手动发送
    public static final int MODE_CONTROL = 1; // 控制模式 定时发送
    public static final int MODE_SILENT = 2;  // 静默模式，不发送，只接受数据包
    public static final int MODE_TRIGGERED = 3;  // 触发模式，仅在触发后发送


    public static final int STATE_IDLE = 0;
    public static final int STATE_SCANNING = 1;
    public static final int STATE_CONNECTING = 2;
    public static final int STATE_CONNECTED = 3;

    private int mode = MODE_CHAT;
    public int state  = STATE_IDLE;

    private int MAX_BLE_BUFFER_LENGTH = 20;

    private boolean isPastPowerOn = true;
    private boolean toScan = false;
    public boolean runWithArrayAdapter = false;
    private long startTime = 0;

    private boolean isWritingBusy=false;

    private Context context;


    private final Object sendLock = new Object();
    private final Object socket_out_lock = new Object();

    private BluetoothAdapter adapter;
    private BluetoothLeScanner scanner;
    private BluetoothSocket socket;

    private BluetoothGatt gatt;
    private BluetoothGattService service;
    private BluetoothGattCharacteristic tx_characteristic,rx_characteristic;
    private Set<BluetoothDevice> bondedDevices;
    private ManagerThread managerThread;
    private TxThread txThread;
    private RxThread rxThread;

    private int tx_period = 200;
    private long lastSendTime;
    private static final int SEND_OVER_TIME =300;
    private static final int MANAGE_PERIOD = 200;

    private int read_stack=0;

    private long readIndex=0;
    private long recvIndex=0;

    private byte[] rxBuffer = new byte[MAX_BUFFER_SIZE];

    private TxPackage txPackage;
    private RxPackage rxPackage;
    private PackageStructure rxStructure = new PackageStructure(8,1,1,2,3);
    private PackageStructure txStructure = new PackageStructure(0,0,0,0,0);


    boolean isFilterDevice = false;
    String[] namesToFilter ;


    private int leftTxTimes = 0;

    public void trigger(int extra_pack)
    {
        if(mode==MODE_TRIGGERED)
        {
            leftTxTimes = extra_pack+1;
        }
    }

    private static final String TAG = "BlueToothMaster";

    public String[] getUUIDByMAC(String mac)
    {
        String [] list = new String[3];
        list[0] = uuidPreference.getString(mac+".service","0000ffe0-0000-1000-8000-00805f9b34fb");
        list[1] = uuidPreference.getString(mac+".tx_char","0000ffe1-0000-1000-8000-00805f9b34fb");
        list[2] = uuidPreference.getString(mac+".rx_char","0000ffe1-0000-1000-8000-00805f9b34fb");

        Log.w(TAG, "getUUIDByMAC: "+list[0] +"\n"+list[1] +"\n"+list[2] );
        return list;
    }
    public void putUUID(String mac,String service,String tx_char,String rx_char)
    {
        Log.w(TAG, "putUUID: "+mac + "\n"+service+"\n"+tx_char +"\n"+rx_char);
        uuidPreference.edit().putString(mac+".service",service).putString(mac+".tx_char",tx_char).putString(mac+".rx_char",rx_char).apply();
    }


    private SharedPreferences uuidPreference;

    private void initUUIDList(Context context)
    {
        uuidPreference = context.getSharedPreferences("uuid_list",Context.MODE_PRIVATE);
    }

    public void setDeviceFilter(boolean enable,String nameString)
    {


        isFilterDevice = enable;

        Log.w(TAG, "setDeviceFilter: "+enable);
        if(nameString!=null&&nameString.length()>0)
        {
            namesToFilter = nameString.split(" ");

            for(String s:namesToFilter)
                Log.w(TAG, "setDeviceFilter:"+s +"   "+s.length());
        }
    }

    private boolean canPassFilter(String name)
    {
        if(isFilterDevice&&name!=null&&namesToFilter.length>0)
        {
            for (String part:namesToFilter)
            {
                if(part.length()>0&&name.toUpperCase().contains(part.toUpperCase()))
                    return true;
            }
        }
        return false;
    }


    public void setRxStructure(int nbl,int nb,int ns,int ni,int nf)
    {
        rxStructure = new PackageStructure(nbl,nb,ns,ni,nf);
    }

    public void setListener(BlueToothEventListener listener)
    {
        this.listener = listener;
    }
    public BlueToothEventListener getListener()
    {
        return this.listener;
    }

    public void linkListView(ListView listView,int item_id,int bt_classic,int bt_le,int connect,int disconnect)
    {
        arrayAdapter = new BlueToothDeviceAdapter(item_id,bt_classic,bt_le,connect,disconnect);
        runWithArrayAdapter = true;
        listView.setDividerHeight(0);
        listView.setAdapter(arrayAdapter);
        lv = listView;
    }

    void  bigSmall(final View view)
    {
        Animation a = AnimationUtils.loadAnimation(context,R.anim.big_small);
        final Animation b = AnimationUtils.loadAnimation(context,R.anim.big_small_2);

        a.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {
            }
            @Override
            public void onAnimationEnd(Animation animation) {
                view.startAnimation(b);
            }
            @Override
            public void onAnimationRepeat(Animation animation) {
            }
        });
        view.startAnimation(a);
    }


    BlueToothDeviceAdapter arrayAdapter;

    boolean toShowUUIDDialog = false;

    ListView lv;
    class BlueToothDeviceAdapter extends ArrayAdapter
    {
        int item_layout_id ;
        int bt_classic_id;
        int bt_le_id;
        int connect_id;
        int disconnect_id;

        BlueToothDeviceAdapter(int item_id,int bt_classic,int bt_le,int connect,int disconnect) {
            super(context, item_id, devices);
            item_layout_id = item_id;
            bt_classic_id = bt_classic;
            bt_le_id = bt_le;
            connect_id = connect;
            disconnect_id = disconnect;
        }

        @Override
        public View getView(final int position, View convertView, ViewGroup parent) {

            final BluetoothDevice device = (BluetoothDevice) getItem(position);

            View view;
            if(convertView==null)
                view = LayoutInflater.from(context).inflate(item_layout_id,parent,false);
            else
                view = convertView;

            TextView tv = view.findViewById(R.id.name);
            TextView add = view.findViewById(R.id.address);
            ImageView settings = view.findViewById(R.id.device_set);

            //LinearLayout area = view.findViewById(R.id.total_area);
            ImageView icon = view.findViewById(R.id.icon);
            final DeviceConnectView con = view.findViewById(R.id.con);
            con.master = BlueToothMaster.this;
            con.device = device;

            if(device!=null&&device.getType()==BluetoothDevice.DEVICE_TYPE_LE) {
                icon.setImageResource(bt_le_id);
                settings.setVisibility(View.VISIBLE);
            }
            else {
                icon.setImageResource(bt_classic_id);
                settings.setVisibility(View.GONE);
            }

            settings.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    bigSmall(v);

                    toShowUUIDDialog = true;
                    if(state!=STATE_CONNECTED)
                        connect((BluetoothDevice)getItem(position));
                    //else
                      //  uiHandler.toastString("请先断开连接");

                    //Log.w("STATE","state:"+state+device.getAddress());
//                    if(device!=null&&device.getAddress()!=null&&deviceConnected!=null&&!device.getAddress().equals(deviceConnected.getAddress())) {
//                        //con.start();
//                        connect((BluetoothDevice) getItem(position));
//                    }else
//                    {
//                        if(state!=STATE_CONNECTED) {
//                            //con.start();
//                            connect((BluetoothDevice) getItem(position));
//                        }else
//                        {
//                            //con.stop();
//                            disconnect();
//                        }
//                    }

                }
            });

            con.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {

                    toShowUUIDDialog = false;
                    //Log.w("STATE","state:"+state+device.getAddress());
                    if(device!=null&&device.getAddress()!=null&&deviceConnected!=null&&!device.getAddress().equals(deviceConnected.getAddress())) {
                        //con.start();
                        connect((BluetoothDevice) getItem(position));
                    }else
                    {
                        if(state!=STATE_CONNECTED) {
                            //con.start();
                            connect((BluetoothDevice) getItem(position));
                        }else
                        {
                            //con.stop();
                            disconnect();
                        }
                    }
                }
            });
            if(device!=null) {
                String s = device.getName();
                if(s!=null)
                    tv.setText(s);
                else
                    tv.setText("未知设备");

                add.setText(device.getAddress());
            }
            return view;
        }
    }





    public class PackageStructure
    {
        int numBoolean=0;
        int numInteger=0;
        int numByte =0;
        int numShort=0;
        int numFloat=0;

        int packLength = 3;      //  由程序自动计算出总长度
        int packDataLength = 0;  //  去除打包相关的字节的纯数据长度

        public PackageStructure(int nbool,int nbyte,int nshort,int nint,int nfloat)
    {
        numBoolean = nbool;
        numByte = nbyte;
        numShort = nshort;
        numInteger = nint;
        numFloat = nfloat;
        packDataLength = (nbool+7)/8 + nbyte+nshort*2+nint*4+nfloat*4;
        packLength = packDataLength+3;

    }
        public PackageStructure(int [] channels)
        {
            numBoolean = channels[0];
            numByte = channels[1];
            numShort = channels[2];
            numInteger = channels[3];
            numFloat = channels[4];
            packDataLength = (channels[0]+7)/8 + channels[1]+channels[2]*2+channels[3]*4+channels[4]*4;
            packLength = packDataLength+3;

        }

    }

    private BlueToothEventListener listener;
    private BroadcastReceiver receiver;
    private ScanCallback callback;

    private List<TxData> txDataQueue=new ArrayList<>();


    public List<BluetoothDevice> devices;

    BluetoothDevice deviceToConnect;
    BluetoothDevice deviceConnected;
    private boolean toConnect = false;
    private boolean new_device=false;
    private final  int RX_BLE_DATA_BUFFER_SIZE = 4096;
    private byte[] rxBLEDataBuffer = new byte[RX_BLE_DATA_BUFFER_SIZE];
    private int rxBLEDataLength = 0;
    private long lastBLERxTime=0;

    private OutputStream outputStream;
    private InputStream inputStream;


    int noResponseTime = 0;

    class TxData{
        byte[] data;
        int length;
        private TxData(byte[] b,int l)
        {
            data = b;
            length = l;
        }
    }

    private static final int STATISTIC_PERIOD = 1000;
    int statisticCount=0;
    long lastStatisticTime=0;
    int txCount=0;
    int rxCount=0;
    int errCount=0;
    Statistic statistic=new Statistic();
    public class Statistic
    {
        public int tx;
        public int rx;
        public int txRate;
        public int rxRate;
        public int error;
        public int errorRate;
    }


    /**
     * 获取当前的收发统计信息，包括收发字节数，错误字节数以及收发速率
     *
     * @return 当前的收发统计数据
     */
    public Statistic getStatistic()
    {
        return  statistic;
    }

    final BluetoothManager manager;
    public BlueToothMaster(Context context, BlueToothEventListener l) {
        // 首先检测蓝牙搜索用到的粗略位置的权限

        mode = MODE_CHAT;
        this.context = context;
        this.listener = l;
        if(Build.VERSION.SDK_INT>=23)
          if(context.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION)!= PackageManager.PERMISSION_GRANTED)
          {
              ((Activity)context).requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},12);
          }
        initUUIDList(context);
        manager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);
        if (manager != null)
            adapter = manager.getAdapter();
        if (adapter != null)
            scanner = adapter.getBluetoothLeScanner();
        else
        {
            adapter = BluetoothAdapter.getDefaultAdapter();
            scanner = adapter.getBluetoothLeScanner();
        }

        if(adapter==null)
        {
            Toast.makeText(context,"手机蓝牙状态异常",Toast.LENGTH_SHORT).show();
            ((Activity)context).finish();
            return;
        }
        isPastPowerOn = adapter.isEnabled();

        devices = new ArrayList<>();

        callback = new ScanCallback() {
            @Override
            public void onScanResult(int callbackType, ScanResult result) {

                BluetoothDevice device = result.getDevice();
                if(device!=null)
                {
                    if(device.getType()!=0&&!devices.contains(device)) {

                        if(isFilterDevice)
                        {
                            if(!canPassFilter(device.getName()))
                                return;
                        }

                        if(runWithArrayAdapter&&arrayAdapter!=null)
                            arrayAdapter.add(device);
                        else
                            devices.add(device);

                        int s = result.getRssi();

                        Log.w("SCAN BLE",device.getName()+ "   " +s+"  "+isFilterDevice+"  ");

                        if(listener!=null)
                            listener.onScannedDevice(devices,device);
                    }

                }
            }
        };
        receiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {

                // 搜索到设备
                if(BluetoothDevice.ACTION_FOUND.equals(intent.getAction()))
                {
                    BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                    if(device!=null&&device.getType()!=BluetoothDevice.DEVICE_TYPE_UNKNOWN&&!devices.contains(device)) {


                        if(isFilterDevice)
                        {
                            if(!canPassFilter(device.getName()))
                                return;
                        }

                        if(runWithArrayAdapter&&arrayAdapter!=null)
                            arrayAdapter.add(device);
                        else
                            devices.add(device);

                        short s = intent.getShortExtra(BluetoothDevice.EXTRA_RSSI,(short)0);

                        Log.w("SCAN",device.getName()+ "   " +s+"  "+isFilterDevice+"  ");

                        if(listener!=null)
                            listener.onScannedDevice(devices,device);
                    }
                }

                // 搜索结束
                if(BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(intent.getAction())) {
                    adapter.getBluetoothLeScanner().stopScan(callback);
                    if(scanner!=null)
                        scanner.stopScan(callback);

                    for(BluetoothDevice device:devices)
                    {
                        Log.w("DEVICE",device.getName()+"  "+device.getAddress()+"  "+device.getType());
                    }
                    state = STATE_IDLE;
                    if(listener!=null)
                        listener.onScanningFinished();
                }

                if(BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(intent.getAction())) {

                    BluetoothDevice d = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                    int b= d.getBondState();
                    if(b==BluetoothDevice.BOND_NONE)
                    Toast.makeText(context,"配对失败",Toast.LENGTH_SHORT).show();

                    if(b==BluetoothDevice.BOND_BONDED) {

                        listener.onPaired();
                        Toast.makeText(context, "配对成功", Toast.LENGTH_SHORT).show();
                    }//if(b==BluetoothDevice.BOND_BONDED&&deviceToBond!=null)
                      //  connect(deviceToBond);
                }
            }
        };

        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(BluetoothDevice.ACTION_FOUND);
        intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
        intentFilter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);
        intentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
        //intentFilter.addAction();


        context.registerReceiver(receiver,intentFilter);

        txPackage = new TxPackage();
        rxPackage = new RxPackage();

        managerThread = new ManagerThread();
        txThread = new TxThread();
        rxThread = new RxThread();

        managerThread.start();
        txThread.start();
        rxThread.start();

        //startScan();
    }


    /**
     * 开始扫描周围设备，扫描对象包括各个版本的蓝牙设备
     *   BT2.0~5.0
     */
    public void startScan()
    {
        startTime = SystemClock.uptimeMillis();

        if(!toScan)
            toScan = true;
        if(runWithArrayAdapter&&arrayAdapter!=null)
            arrayAdapter.clear();
        else
            devices.clear();

        if(state==STATE_CONNECTED)
        {
            if(runWithArrayAdapter&&arrayAdapter!=null)
                arrayAdapter.add(deviceConnected);
            else
                devices.add(deviceConnected);
        }

       state = STATE_SCANNING;
    }

    private void requestBondDevice(BluetoothDevice d)
    {
        Log.w("DEVICE","bond:"+d.getName());

        d.createBond();
    }


    /**
     * 连接蓝牙设备，该设备一般是从扫描设备列表中选择的
     * @param device 要连接的设备
     */
    public void connect(BluetoothDevice device)
    {
        if(device.getType()==BluetoothDevice.DEVICE_TYPE_LE||device.getBondState()==BluetoothDevice.BOND_BONDED) {
            toConnect = true;
            if ((state == STATE_CONNECTED) && (deviceToConnect != null) && (deviceToConnect != device)) {
                new_device = true;
            }
            deviceToConnect = device;
            stopScan();
        }else {

            disconnect();
            requestBondDevice(device);
        }Log.w("CON","new connection");

    }

    /**
     * 断开设备，注意该方法是异步的，由状态管理线程处理，该线程处理间隔为MANAGE_PERIOD
     */
    public void disconnect()
    {
        Log.w("DIS","cancel");
        toConnect = false;
    }


    public void stopScan()
    {
        if(adapter!=null&&adapter.isDiscovering())
        adapter.cancelDiscovery();
        if(scanner!=null)
        scanner.stopScan(callback);
    }



    //public MainActivity.UIHandler uiHandler;

    private BluetoothGattCallback gattCallback = new BluetoothGattCallback() {
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {

            Log.w("GATT","connect--"+newState);

            //MAX_BLE_BUFFER_LENGTH =;

            if(newState==BluetoothGatt.STATE_CONNECTED)
            {
//                if(gatt.requestMtu(MAX_BLE_BUFFER_LENGTH))
//                    Log.w("MTU","set ok");
//                else {
//                    Log.w("MTU", "set error");
//                    MAX_BLE_BUFFER_LENGTH = 20;
//                }
                gatt.discoverServices();
            }

            if(newState==BluetoothGatt.STATE_CONNECTING)
                state = STATE_CONNECTING;

            if(newState==BluetoothGatt.STATE_DISCONNECTED)
            {
                if(rx_characteristic!=null)
                gatt.setCharacteristicNotification(rx_characteristic,false);
                gatt.close();
                state = STATE_IDLE;
                listener.onDisConnected();
                disconnect();
            }
        }
        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {

            List<BluetoothGattService> ss = gatt.getServices();
            Log.w(">>----","-----");
            for(BluetoothGattService s:ss) {
                List<BluetoothGattCharacteristic> cs;
                cs = s.getCharacteristics();
                Log.w("GATT", "service--" + s.getUuid());

                for(BluetoothGattCharacteristic c:cs)
                    Log.w("GATT","   characteristic---"+c.getUuid());
            }
            Log.w("----","-----<<");

            if(toShowUUIDDialog)
            {

                //uiHandler.showUUIDSettingDialog(gatt);
                disconnect();
                return;
            }

            String[] uuids = getUUIDByMAC(gatt.getDevice().getAddress());


            service = gatt.getService(UUID.fromString(uuids[0]));
            if(service==null) {
                //uiHandler.showUUIDSettingDialog(gatt);
                disconnect();
            }else
            {
                tx_characteristic  =service.getCharacteristic(UUID.fromString(uuids[2]));
                rx_characteristic = service.getCharacteristic(UUID.fromString(uuids[1]));

                if(tx_characteristic==null||rx_characteristic==null)
                {
                    //uiHandler.showUUIDSettingDialog(gatt);
                    disconnect();
                }else   /// JDY - 08
                {
                    boolean set =gatt.setCharacteristicNotification(rx_characteristic,true);
                    state = STATE_CONNECTED;
                    BluetoothGattDescriptor dsc =rx_characteristic.getDescriptor(UUID.fromString(  "00002902-0000-1000-8000-00805f9b34fb"));
                    byte[]bytes = {0x01,0x00};
                    if(dsc!=null) {
                        dsc.setValue(bytes);
                        boolean d = gatt.writeDescriptor(dsc);
                        Log.w(TAG, "onServicesDiscovered: " + set + "  " + d);
                    }
                    listener.onConnected(deviceConnected);
                }
            }
        }



        @Override
        public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {

        }

        @Override
        public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {

            //Log.w(TAG, "onCharacteristicChanged: ");

            lastBLERxTime = SystemClock.uptimeMillis();
            readBLE(characteristic.getValue(),characteristic.getValue().length);

        }
        @Override
        public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            synchronized (sendLock) {
                sendLock.notify();
            }
        }

        @Override
        public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {

            Log.w("MTU","mtu: "+mtu);
            MAX_BLE_BUFFER_LENGTH = mtu-3;

        }
    };

    /**
     * 将数据放入发送队列中，如果队列拥挤，则有失败可能
     * @param b 要发送的字节数组
     * @param l 要发送的字节数组的长度
     */
    public void pushSend(byte[] b,int l)
    {
        if(state==STATE_CONNECTED&&txDataQueue.size()<10&&mode==MODE_CHAT)
        txDataQueue.add(new TxData(b,l));
    }


    /**
     * 可以选择 聊天模式 或者 控制模式
     *   聊天模式：通过pushSend方法发送字节数据 通过callback的onReceived接收字节数据
     *   控制模式：自动以指定周期发送控制包，并等待接收状态包
     *           在callback的onPreSend 方法中通过add方法将待发送的数值添加进数据包
     *           在callback的onReceived方法中读取接收的数据包的数值
     *           控制模式下可以支持 bool,byte,short,int,float数值的打包发送
     *           前提是需要在通信的另一端设置好包的格式
     * @param newMode 要设置的模式
     */
    public void setMode(int newMode)
    {
        mode = newMode;
    }

    private void send(byte[] data,int length)
    {
        long start =  SystemClock.uptimeMillis();
        if(data.length<length)
            length = data.length;

        if(state==STATE_CONNECTED)
        {
            txCount += length;
            if(deviceConnected==null)
                return;
            if(deviceConnected.getType()==BluetoothDevice.DEVICE_TYPE_LE)
            {
                if(tx_characteristic!=null)
                {
                    // 判断数据包的大小，如果超过MAX_BLE_BUFFER_LENGTH(20) 则将数据分成MAX_BLE_BUFFER_LENGTH长度的小包发送
                    // 在发送过程中，需要与发送回调函数配合，得到写空闲的状态
                    int sendIndex = 0;
                    int l;
                    synchronized (sendLock)
                    {

                    while (sendIndex<length) {

                        isWritingBusy = true;
                        lastSendTime = SystemClock.uptimeMillis();

                        if(length-sendIndex>MAX_BLE_BUFFER_LENGTH)
                            l = MAX_BLE_BUFFER_LENGTH;
                        else
                            l = length-sendIndex;

                        byte[] b = new byte[l];
                        System.arraycopy(data, sendIndex, b, 0, l);
                        tx_characteristic.setValue(b);
                        gatt.writeCharacteristic(tx_characteristic);

                        try {
                            sendLock.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        isWritingBusy = false;

                        sendIndex+=l;
                    }
                    }
                }
            }else // 传统蓝牙设备
            {
                synchronized (socket_out_lock) {



                    if (outputStream != null&&socket.isConnected()) {
                        try {
                            //Log.w("SEND","--SPP"+length);
                            outputStream.write(data, 0, length);
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }

      //  Log.w("TIME","---"+(SystemClock.uptimeMillis()-start)+"ms"+state+"   "+deviceConnected.getName());
    }

    private void readBLE(byte[] data,int length)
    {
        rxCount+=length;
        if(mode == MODE_CHAT)
        {
            if(rxBLEDataLength<=RX_BLE_DATA_BUFFER_SIZE-MAX_BLE_BUFFER_LENGTH)
            {
                System.arraycopy(data,0,rxBLEDataBuffer,rxBLEDataLength,length);
                rxBLEDataLength+=length;
            }
            if(rxBLEDataLength>RX_BLE_DATA_BUFFER_SIZE-MAX_BLE_BUFFER_LENGTH)
            {
                listener.onReceived(rxBLEDataBuffer,rxBLEDataLength);
                rxBLEDataLength = 0;
            }
        }else
            readToBuffer(data,length);

    }

    private boolean connectDevice(BluetoothDevice device)
    {
        boolean isOK = false;


        if(device.getType()==BluetoothDevice.DEVICE_TYPE_LE)   // BLE 设备连接 主要是JDY08透传模块
        {
            Log.w("BEL","connect");

            gatt = device.connectGatt(context,true,gattCallback);

        }else{  // 传统蓝牙设备 连接 主要是HC-05 HC-06
            try {
                //socket = device.createInsecureRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
                socket = device.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
                if(socket==null)
                    Log.w("Connct","error");
                else {
                    socket.connect();
                }
            } catch (IOException e) {
                e.printStackTrace();
                isOK = false;
            }
        }
        return isOK;
    }

    private boolean disconnectDevice(BluetoothDevice device)
    {
        boolean isOK=true;
        if(device.getType()==BluetoothDevice.DEVICE_TYPE_LE)   // BLE 设备断开 主要是JDY08透传模块
        {
            if(rx_characteristic!=null)
                gatt.setCharacteristicNotification(rx_characteristic,false);
            gatt.close();
            gatt.disconnect();

        }else{     // 传统蓝牙设备 断开 主要是HC-05 HC-06

            synchronized (socket_out_lock)
            {
                if(socket!=null&&socket.isConnected())
                {
                    try {
                        socket.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        return isOK;
    }


    /**
     * 清零历史收发统计信息
     */
    public void clearStatistic()
    {
        statistic.tx = 0;
        statistic.rx = 0;
        statistic.txRate = 0;
        statistic.rxRate=0;
        statistic.error = 0;
        statistic.errorRate = 0;
    }
    private void updateStatistic()
    {
        long currentTime = SystemClock.uptimeMillis();
        int delta,xd;
        if(lastStatisticTime!=0)
        {
            delta = (int)(currentTime-lastStatisticTime);

            statistic.tx+=txCount;
            statistic.rx+=rxCount;
            statistic.error+=errCount;

            if(delta>0) {
                xd = txCount * 1000 / delta;

                statistic.txRate += (xd-statistic.txRate)/2;
                if(xd==0)
                    statistic.txRate = 0;
                xd = rxCount * 1000 / delta;
                statistic.rxRate += (xd-statistic.rxRate)/2;
                if(xd ==0)
                    statistic.rxRate = 0;

                xd = errCount *1000/delta;

                statistic.errorRate +=(xd-statistic.errorRate)/2;
                if(xd==0)
                    statistic.errorRate = 0;
            }


            if(listener!=null)
                listener.onStatisticUpdated(statistic);
            txCount=0;
            rxCount=0;
            errCount=0;
        }
        lastStatisticTime = currentTime;
    }

    class ManagerThread extends Thread
    {
        boolean isr=true;
        @Override
        public void run() {
            while (isr)
            {
                // 首先判断蓝牙是否打开
                if(adapter.isEnabled()) {

                    if(bondedDevices==null)
                    {
                     bondedDevices = adapter.getBondedDevices();
                    }
                    if(toScan)
                    {
                        if(scanner==null)
                            scanner = adapter.getBluetoothLeScanner();
                        adapter.startDiscovery();

                        Log.w(TAG, "run: StartBLE");
                        scanner.startScan(callback);

                        toScan = false;
                        if(listener!=null)
                            listener.onScanningStarted();
                    }


                        if (toConnect) {
                            if (deviceToConnect != null) {
                                if (state == STATE_CONNECTED) {

                                   // pushSend("good you are".getBytes(),9);

                                    if(statisticCount>STATISTIC_PERIOD)
                                    updateStatistic();
                                    else
                                        statisticCount+=MANAGE_PERIOD;

                                    if(deviceConnected!=null) {

                                        if (deviceConnected.getType() == BluetoothDevice.DEVICE_TYPE_LE) {
                                            if (isWritingBusy) {

                                                long  d = SystemClock.uptimeMillis()-lastSendTime;

                                                //Log.w("NRT",""+d);
                                                if (d > SEND_OVER_TIME) {
                                                    isWritingBusy = false;
                                                    synchronized (sendLock) {
                                                        sendLock.notify();
                                                        Log.w("Conn", "give up");
                                                    }
                                                    noResponseTime+=100;
                                                }else
                                                {
                                                    if(noResponseTime>=5)
                                                    noResponseTime = noResponseTime-5;
                                                }
                                            }else
                                                noResponseTime = 0;
                                            //Log.w("NRT",""+noResponseTime);
                                        } else {
                                            if (!socket.isConnected()) {
                                                state = STATE_IDLE;
                                                listener.onDisConnected();
                                                Log.w("Conn", "lost");
                                            }
                                        }
                                    }
                                    //Log.w("Conn", "connected" + deviceConnected.getName());
                                    if (new_device)  //  在连接一台设备时，点击了另一台设备，因此需要先断开旧设备然后连接新设备
                                    {
                                        // 此处执行断开操作
                                        disconnectDevice(deviceConnected);

                                        Log.w("Conn", "disconnect" + deviceConnected.getName());
                                        state = STATE_IDLE;
                                    }
                                } else if(state==STATE_IDLE) {    // 设备空闲或者正在连接

                                    state = STATE_CONNECTING;
                                    // 此处执行连接操作
                                    Log.w("Conn", "connecting" + deviceToConnect.getName());
                                    connectDevice(deviceToConnect);
                                    deviceConnected = deviceToConnect;
                                    new_device = false;
                                }else if(state==STATE_CONNECTING)
                                {
                                    if(deviceToConnect.getType()!=BluetoothDevice.DEVICE_TYPE_LE)
                                    {
                                        if(socket!=null&& socket.isConnected())
                                        {
                                            try {
                                                outputStream = socket.getOutputStream();
                                                inputStream = socket.getInputStream();
                                                state = STATE_CONNECTED;

                                                listener.onConnected(deviceConnected);
                                                Log.w("Conn","connected");
                                            } catch (IOException e) {
                                                e.printStackTrace();
                                                Log.w("Conn","error");
                                            }
                                        }
                                    }
                                }
                            }
                        } else  // 断开连接
                        {

                            if(statistic.tx!=0||statistic.rx!=0||statistic.error!=0) {
                                statistic.rxRate = 0;
                                statistic.txRate = 0;
                                statistic.errorRate = 0;
                                statistic.tx = 0;
                                statistic.rx = 0;
                                if (listener != null)
                                    listener.onStatisticUpdated(statistic);
                            }

                            if ((state == STATE_CONNECTED||state==STATE_CONNECTING) && deviceConnected != null)  // 如果当前已有连接
                            {
                               disconnectDevice(deviceConnected);
                               state = STATE_IDLE;
                               listener.onDisConnected();
                               Log.w("Conn", "disconnect" + deviceConnected.getName());
                            }
                        }

                }else // 蓝牙没有打开，需要打开
                {
                    adapter.enable();

                    try {
                        while (!adapter.isEnabled())
                        sleep(500);
                        listener.onPowerOn();
                    }catch (InterruptedException e)
                    {
                        e.printStackTrace();
                    }
                }
                try {
                    sleep(MANAGE_PERIOD);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 设置CONTROL模式下发送数据包的间隔
     * @param ms 间隔单位为毫秒
     */
    public void setTxPeriod(int ms)
    {
        tx_period = ms;
        if(tx_period < 10)
            tx_period = 10;
        if(tx_period > 10000)
            tx_period = 10000;
    }

    class TxThread extends Thread
    {
        boolean isr = true;
        int tx_count=0;
        int max_step = 50;
        int delta = 0;

        @Override
        public void run() {
            while (isr)
            {
                if(mode!=MODE_CHAT) {

                    switch (mode) {
                        case MODE_CONTROL:
                            leftTxTimes = 1;
                            break;
                        case MODE_SILENT:
                            leftTxTimes = 0;
                            break;
                    }
                    if(leftTxTimes>0) {
                        delta = tx_period - tx_count;
                        if (delta > 0) {
                            try {

                                if (delta <= max_step) {
                                    sleep(delta);
                                    tx_count += delta;
                                } else {
                                    sleep(max_step);
                                    tx_count += max_step;
                                }

                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        } else {
                            if (state == STATE_CONNECTED)
                                sendPackage();
                            tx_count = 0;
                            leftTxTimes--;
                        }
                    }else
                    {
                        try {
                            sleep(max_step);
                            tx_count = tx_period;
                        }catch (InterruptedException e)
                            {
                                e.printStackTrace();
                            }
                    }
                }else
                {
                    try {
                        sleep(50);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    if(state==STATE_CONNECTED)
                        sendQueue();
                }
            }
        }

        void sendPackage()  // Send per tx_period ms
        {
            //Log.w("SEND","delta:"+delta+"  tc:"+tx_count+"  tp:"+tx_period);

            txPackage.clear();
            listener.onPreSend(txPackage);
            txPackage.pack();
            if(txPackage.pack_length>0)
            send(txPackage.pack_data,txPackage.pack_length);
        }

        void sendQueue()
        {
            if(txDataQueue.size()>0) {
                for (TxData td : txDataQueue) {
                    send(td.data, td.length);
                    if(listener!=null)
                        listener.onDataSent(td.data,td.length);
                }
                txDataQueue.clear();
            }
        }
    }

    @SuppressLint("HandlerLeak")
    class DelayHandler extends Handler
    {
        long start_time;

         void readStarted(long this_time)
        {
            if(mode==MODE_CHAT) {
                read_stack++;
                start_time = this_time;
                //Log.w("RECH","started_read");
                sendEmptyMessageDelayed(1, waitMs);
            }
        }

        void sendStarted()
        {
            sendEmptyMessageDelayed(2,SEND_OVER_TIME);
        }

        @Override
        public void handleMessage(Message msg) {

            if(msg.what==1)
            {
                read_stack--;
                if(read_stack==0)
                {
                    rxThread.onChatRecv();
                }
            }

        }
    }

    private DelayHandler recHandler = new DelayHandler();


    public void setWaitMs(int ms)
    {
        waitMs = ms;
    }

    int waitMs = 50;

    class RxThread extends Thread
    {
        boolean isr = true;
        int length = 0;
        int dLength=0;
        final int TMP_RX_BUFFER = 8192;
        int TMP_RX_THRES=TMP_RX_BUFFER/2;

        byte[] tmpRxBuffer = new byte[TMP_RX_BUFFER];
        byte[] dRxBuffer = new byte[TMP_RX_BUFFER];

        void onChatRecv()
        {
            listener.onReceived(tmpRxBuffer,length);
            length = 0;
        }

        @Override
        public void run() {
            while (isr)
            {
                try {
                    sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if(state==STATE_CONNECTED&&deviceConnected!=null) {
                    if (deviceConnected.getType() == BluetoothDevice.DEVICE_TYPE_LE) {

                        if(mode == MODE_CHAT)   // 只有对话模式才对数据根据时间进行分割
                        {
                            if (rxBLEDataLength > 0 && SystemClock.uptimeMillis() - lastBLERxTime > waitMs) {

                                listener.onReceived(rxBLEDataBuffer,rxBLEDataLength);
                                rxBLEDataLength = 0;
                            }
                        }
                    } else {
                        // 经典蓝牙设备
                        // 在此 InputStream 堵塞式接收

                        if(inputStream!=null&&socket.isConnected())
                        {
                            try {
                                recHandler.readStarted(SystemClock.uptimeMillis());
                                dLength = inputStream.read(dRxBuffer);
                                rxCount +=dLength;
                            } catch (IOException e) {
                                e.printStackTrace();
                                state = STATE_IDLE;
                                listener.onDisConnected();
                                Log.w("CONN","lost");
                                if(!new_device)
                                disconnect();
                            }
                        }else
                        {
                            state = STATE_IDLE;
                            listener.onDisConnected();
                            Log.w("CONN","lost");
                        }
                        if(dLength>0)
                        {
                            if(mode == MODE_CHAT)
                            {
                                System.arraycopy(dRxBuffer,0,tmpRxBuffer,length,dLength);
                                length+=dLength;
                                if(length>TMP_RX_THRES)
                                    onChatRecv();
                            }else
                                readToBuffer(dRxBuffer,dLength);
                        }
                    }
                }
            }
        }
    }


    /**
     * 程序退出时必须调用此方法，否则会有不可预料的后果
     * @param context Activity的context
     */
    public void onDestroy(Context context)
    {
        if(state==STATE_CONNECTED&&deviceConnected!=null)
        disconnectDevice(deviceConnected);
        context.unregisterReceiver(receiver);
        scanner.stopScan(callback);
        managerThread.isr = false;
        txThread.isr = false;
        rxThread.isr = false;
        try {
            managerThread.join();
        }catch (InterruptedException e)
        {
            e.printStackTrace();
        }
        if(!isPastPowerOn)
        if(adapter!=null)
            adapter.disable();
    }

    public class TxPackage
    {

        //static final boolean IS_LITTLE_ENDIAN = true;

        // 打包好的字节数据存放在此，记录总长度
        byte[] pack_data = new byte[MAX_PACK_SIZE];
        int pack_length = 0;

        // 支持的所有数据类型均以list形式存储

        List<Boolean> booleans = new ArrayList<>();  // true-1 | false-0
        List<Byte> bytes = new ArrayList<>();        // -128 ~ 127
        List<Short> shorts = new ArrayList<>();      // -32768 ~ 32767
        List<Integer> integers = new ArrayList<>();  // -2xxxxxxxx ~ 2xxxxxxxx
        List<Float> floats  =  new ArrayList<>();    //        ....

        // 在发送时，需要先将之前的数据清空
        void clear()
        {
            booleans.clear();
            bytes.clear();
            shorts.clear();
            integers.clear();
            floats.clear();
        }
        // 数据清空后，添加新的数据
        public void add(boolean b)
        {
            booleans.add(b);
        }
        public void add(byte b)
        {
            bytes.add(b);
        }
        public void add(short b)
        {
            shorts.add(b);
        }
        public void add(int b)
        {
            integers.add(b);
        }
        public void add(float b)
        {
            floats.add(b);
        }

        // 将待发送的数据打包为字节数组 包括 包头+校验+内容
        void pack()
        {
         int tpl = 0;
         int byteIndex=0,bitIndex=0;
         pack_data[0] = PACK_HEAD;
         tpl+=1;


         txStructure  = new PackageStructure(booleans.size(),bytes.size(),shorts.size(),integers.size(),floats.size());

         byteIndex = -1;
         for(int i=0;i<booleans.size();i++)
         {
             byteIndex = i/8;
             bitIndex = i%8;

             if(bitIndex==0)
                 pack_data[tpl+byteIndex]=0;

             if(booleans.get(i)) {
                 pack_data[tpl + byteIndex] |= 0x01 << bitIndex;
             }
         }
         tpl+=byteIndex+1;

         for(int i=0;i<bytes.size();i++)
         {
             pack_data[tpl++] = bytes.get(i);
         }

         short s;
         for(int i=0;i<shorts.size();i++)
         {
             s = shorts.get(i);
             pack_data[tpl++] = (byte) (s&0xff);
             pack_data[tpl++] = (byte)((s>>8)&0xff);
         }
         int it;
         for(int i=0;i<integers.size();i++)
         {
             it = integers.get(i);
             pack_data[tpl++] = (byte) (it&0xff);  // 这个0xff非常重要，不加会导致符号错乱
             pack_data[tpl++] = (byte)((it>>8)&0xff);
             pack_data[tpl++] = (byte)((it>>16)&0xff);
             pack_data[tpl++] = (byte)((it>>24)&0xff);
         }
         for(int i=0;i<floats.size();i++)
         {
             it = Float.floatToRawIntBits(floats.get(i));
             pack_data[tpl++] = (byte) (it&0xff);  // 这个0xff非常重要，不加会导致符号错乱
             pack_data[tpl++] = (byte)((it>>8)&0xff);
             pack_data[tpl++] = (byte)((it>>16)&0xff);
             pack_data[tpl++] = (byte)((it>>24)&0xff);
         }
         int check = 0;
         for(int i=1;i<tpl;i++)
         {
             check+= pack_data[i]&0xff;
         }
         pack_data[tpl++] = (byte) (check&0xff);
         pack_data[tpl++] = PACK_TAIL;

         pack_length = tpl;

         //Log.w("PACK","pack_length:"+pack_length+"  d:"+pack_data[1]+"   c:"+String.format(Locale.getDefault(),"%X",check));
        }
    }
    private void readToBuffer(byte[] new_b,int length) // 将接收的数据传递到RX Buffer中，然后等待解包
    {
        int readIndexInt;
        int dataIndex;
        //Log.w("PackBuffer","read to pack buffer");

        if(length>MAX_BUFFER_SIZE)
            return;

        if((int)(recvIndex%MAX_BUFFER_SIZE)+length<MAX_BUFFER_SIZE)
        System.arraycopy(new_b,0,rxBuffer,(int)(recvIndex%MAX_BUFFER_SIZE),length);
        else
        {
            int l1 = MAX_BUFFER_SIZE - (int)(recvIndex%MAX_BUFFER_SIZE);
            System.arraycopy(new_b,0,rxBuffer,(int)(recvIndex%MAX_BUFFER_SIZE),l1);
            System.arraycopy(new_b,l1,rxBuffer,0,length-l1);
        }
        recvIndex+=length;
        //Log.w("RECV","recv:"+recvIndex+" read:"+readIndex);
        int check = 0;
        while (recvIndex-readIndex>=rxStructure.packLength)
        {
            readIndexInt = (int)(readIndex%MAX_BUFFER_SIZE);
            if(rxBuffer[readIndexInt]==PACK_HEAD&&rxBuffer[(int)((readIndex+rxStructure.packLength-1)%MAX_BUFFER_SIZE)]==PACK_TAIL)
            {
                readIndexInt = ((readIndexInt+1)%MAX_BUFFER_SIZE);
                dataIndex  =  readIndexInt;
                check = 0;
                String s="";
                for(int i=0;i<rxStructure.packDataLength;i++) {
                    s = s.concat(String.format(Locale.getDefault()," %2X",rxBuffer[readIndexInt] & 0xff));
                    check += rxBuffer[readIndexInt++] & 0xff;
                    if(readIndexInt>=MAX_BUFFER_SIZE)
                        readIndexInt-=MAX_BUFFER_SIZE;
                }
                //Log.w("RECV","sum:"+(check&0xff)+" dsum:"+(rxBuffer[readIndexInt]&0xff));
                if((check&0xff)==(rxBuffer[readIndexInt]&0xff))
                {
                    //Log.w("RECV","OK");
                    rxPackage.getData(rxBuffer,dataIndex,rxStructure.packDataLength);
                    rxPackage.unpack();
                    listener.onReceived(rxPackage);
                    readIndex+=rxStructure.packLength;
                    //Log.w("RECV","SUM OK"+"sum:"+(check&0xff)+" dsum:"+(rxBuffer[readIndexInt]&0xff)+s);
                }else {
                    errCount+=1;
                    //Log.w("RECV","SUM ERROR"+"sum:"+(check&0xff)+" dsum:"+(rxBuffer[readIndexInt]&0xff)+s);
                    readIndex+=rxStructure.packLength;
                }
            }else
            {
                errCount+=1;
                //Log.w("RECV","HEAD TAIL ERROR");
                readIndex++;
            }
        }
    }
    public class RxPackage
    {
        byte[] pack_data = new byte[MAX_PACK_SIZE];
        int pack_length = 0;

        int rdIndex;


        List<Boolean> booleans = new ArrayList<>();  // true-1 | false-0
        List<Byte> bytes = new ArrayList<>();        // -128 ~ 127
        List<Short> shorts = new ArrayList<>();      // -32768 ~ 32767
        List<Integer> integers = new ArrayList<>();  // -2xxxxxxxx ~ 2xxxxxxxx
        List<Float> floats  =  new ArrayList<>();    //        ....

        void clear()
        {
            booleans.clear();
            bytes.clear();
            shorts.clear();
            integers.clear();
            floats.clear();
        }

        public boolean getBoolean(int index)
        {
            if(index<booleans.size())
                return booleans.get(index);
            else
                return false;
        }

        public byte getByte(int index)
        {
            if(index<bytes.size())
                return bytes.get(index);
            else
                return 0;
        }

        public short getShort(int index)
        {
            if(index<shorts.size())
                return shorts.get(index);
            else
                return 0;
        }

        public int getInteger(int index)
        {
            if(index<integers.size())
                return integers.get(index);
            else
                return 0;
        }
        public float getFloat(int index)
        {
            if(index<floats.size())
                return floats.get(index);
            else
                return 0;
        }

        void getData(byte[] src,int off,int length)
        {
            if(off+length<=src.length) {
                System.arraycopy(src, off, pack_data, 0, length);
                pack_length = length;
            }else if(off<src.length)
            {
                int left = (src.length-off);
                int right = length-left;
                System.arraycopy(src,off,pack_data,0,left);
                System.arraycopy(src,0,pack_data,left,right);
            }
        }

        // 把接收到的数据解包 //////////////////
        void unpack()
        {
            int byteIndex=0,bitIndex=0;
            clear();

            if(pack_length!=rxStructure.packDataLength)
                return;

            rdIndex = 0;

            if(rxStructure.numBoolean>0) {
                for (int i = 0; i < rxStructure.numBoolean; i++) {
                    byteIndex = i / 8;
                    bitIndex = i % 8;
                    booleans.add((pack_data[byteIndex] & (0x01 << bitIndex)) != 0);
                }
                rdIndex+=byteIndex+1;
            }

            for(int i=0;i<rxStructure.numByte;i++)
                bytes.add(pack_data[rdIndex++]);

            short s;
            for(int i=0;i<rxStructure.numShort;i++) {
                s = (short) (pack_data[rdIndex++]&0xff);
                s = (short) (s|((pack_data[rdIndex++]&0xff)<<8));
                shorts.add(s);
            }

            int it;
            for(int i=0;i<rxStructure.numInteger;i++) {
                it = pack_data[rdIndex++]&0xff;// 这个0xff非常重要，不加会导致符号错乱
                it =  (it|((pack_data[rdIndex++]&0xff)<<8));
                it =  (it|((pack_data[rdIndex++]&0xff)<<16));
                it =  (it|((pack_data[rdIndex++]&0xff)<<24));
                integers.add(it);
            }
            float f;
            for(int i=0;i<rxStructure.numFloat;i++)
            {
                it = pack_data[rdIndex++]&0xff;  // 这个0xff非常重要，不加会导致符号错乱
                it =  (it|((pack_data[rdIndex++]&0xff)<<8));
                it =  (it|((pack_data[rdIndex++]&0xff)<<16));
                it =  (it|((pack_data[rdIndex++]&0xff)<<24));

                f=Float.intBitsToFloat(it);
                floats.add(f);
            }
        }
    }

    /**
     * 蓝牙事件监听器
     */
    public interface BlueToothEventListener
    {
        void onPowerOn();
        void onScanningStarted();
        void onScannedDevice(List<BluetoothDevice> devices, BluetoothDevice newDevice);
        void onScanningFinished();

        void onPaired();
        void onConnected(BluetoothDevice device);
        void onDisConnected();
        void onPreSend(TxPackage tp);
        void onDataSent(byte[] b,int l);
        void onReceived(RxPackage rp);
        void onReceived(byte[] bytes, int length);
        void onStatisticUpdated(Statistic statistic);

    }

}
